<template>
  <!-- 二维码生成器 -->
  <div class="qrcode-generator">
    <!-- 二维码容器 -->
    <div
      class="qrcode-container"
      :style="{ width: `${size}px`, height: `${size}px` }"
    >
      <!-- 使用v-show替代v-if，确保canvas始终存在于DOM中 -->
      <canvas
        ref="qrcodeCanvas"
        :width="size"
        :height="size"
        v-show="isValidContent"
      ></canvas>

      <!-- 内容无效时显示的提示 -->
      <div class="invalid提示" v-show="!isValidContent">请输入有效的内容</div>
    </div>

    <!-- 错误信息 -->
    <p class="error-message" v-if="errorMessage">{{ errorMessage }}</p>
    <div v-if="isPreviewText" class="qr-code-text ">{{previewText}}</div>
  </div>
</template>

<script>
// 导入qrcode库，需要先安装：npm install qrcode --save
import QRCode from "qrcode";

export default {
  name: "QrcodeGenerator",
  props: {
    isPreviewText: {
      type: Boolean,
      default: false,
    },
    // 预览文本
    previewText: {
      type: String,
      default: "扫码预览",
    },
    // 二维码内容
    content: {
      type: String,
      required: true,
    },
    // 二维码尺寸
    size: {
      type: Number,
      default: 200,
      validator: (value) => {
        return value >= 30 && value <= 500; // 限制尺寸范围
      },
    },
    // 二维码前景色
    foregroundColor: {
      type: String,
      default: "#000000",
    },
    // 二维码背景色
    backgroundColor: {
      type: String,
      default: "#ffffff",
    },
    // 二维码容错级别 ('L', 'M', 'Q', 'H')
    errorCorrectionLevel: {
      type: String,
      default: "M",
      validator: (value) => {
        return ["L", "M", "Q", "H"].includes(value);
      },
    },
  },
  data() {
    return {
      errorMessage: "",
      isValidContent: false,
    };
  },
  watch: {
    // 当相关属性变化时重新生成二维码
    content: "generateQrcode",
    size: "generateQrcode",
    foregroundColor: "generateQrcode",
    backgroundColor: "generateQrcode",
    errorCorrectionLevel: "generateQrcode",
  },
  mounted() {
    // 初始化生成二维码
    this.generateQrcode();
  },
  methods: {
    // 生成二维码
    async generateQrcode() {
      // 验证内容是否有效
      if (!this.content || this.content.trim() === "") {
        this.isValidContent = false;
        this.errorMessage = "请输入二维码内容";
        return;
      }

      try {
        this.isValidContent = true;
        this.errorMessage = "";

        // 确保canvas元素已经存在于DOM中
        // 使用v-show替代v-if后，canvas元素始终存在，所以这里可以直接获取
        const canvas = this.$refs.qrcodeCanvas;
        if (!canvas) {
          throw new Error("无法获取canvas元素");
        }

        const ctx = canvas.getContext("2d");

        // 清空画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // 生成二维码
        await QRCode.toCanvas(canvas, this.content, {
          width: this.size,
          margin: 1,
          color: {
            dark: this.foregroundColor,
            light: this.backgroundColor,
          },
          errorCorrectionLevel: this.errorCorrectionLevel,
        });

        // 触发成功事件
        this.$emit("generated", canvas);
      } catch (error) {
        this.errorMessage = `生成二维码失败: ${error.message}`;
        this.$emit("error", error);
      }
    },

    // 下载二维码图片
    downloadQrcode(filename = "qrcode") {
      if (!this.$refs.qrcodeCanvas || !this.isValidContent) return;

      try {
        // 将canvas转换为图片URL
        const dataURL = this.$refs.qrcodeCanvas.toDataURL("image/png");

        // 创建下载链接
        const link = document.createElement("a");
        link.download = `${filename}.png`;
        link.href = dataURL;

        // 触发下载
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);

        // 触发下载成功事件
        this.$emit("downloaded", `${filename}.png`);
      } catch (error) {
        this.errorMessage = `下载二维码失败: ${error.message}`;
        this.$emit("error", error);
      }
    },
  },
};
</script>

<style scoped>
.qr-code-text {
  font-size: 14px;
  color: #323232;
  font-weight: 500;
  text-align: center;
  padding-top: 10px;
}
.qrcode-generator {
  display: inline-block;
  position: relative;
}

.qrcode-container {
  position: relative;
  border: 1px solid #eee;
  border-radius: 4px;
  overflow: hidden;
  background-color: #f9f9f9;
}

.invalid提示 {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  font-size: 14px;
}

.error-message {
  margin: 8px 0 0 0;
  color: #ff4d4f;
  font-size: 12px;
  text-align: center;
}
</style>
